var FormControl = Class.create(BaseControl, {
    options: null,
    hashable:null,
    hash: null,
	isForceRefresh: null,

    checkForChanges: function(){},
    checkForFilterChanges: function(){},
    beforeSubmit: function(){},
    discardAllChanges: function(){},

    initialize: function($super, element, options)
    {
        this.options = this.getDefaultOptions();
        Object.extend(this.options, options || {});
        $super(element);
        this.hashable = this.view.hasClassName('hashable');
        if (this.fresh)
        {
            if (this.hashable)
            {
                this.observeHashChange();
                this.onHashChange(getLocationHash());
            }
            else this.stubLoad();
        }
    },

    stubLoad: function()
    {
        if (this.view.hasClassName('stub'))
        {
            var params = $H();
            this.find('input').each(function(e){
                if (params.get(e.name) == undefined)
                    params.set(e.name, e.value);
            });
            this.ajax(params);
        }
    },

    onHashChange: function(newHash)
    {
        var hs = this.getHash(this.name, newHash);
        if (this.isForceRefresh || this.hash != hs)
        {
			this.isForceRefresh = false;
            this.hash = hs;
            var params = this.hash ? $H(this.hash.toQueryParams()) : $H();
            this.find('input.nohash').each(function(e){
                params.set(e.name, e.value);
            });
            if (this.view.hasClassName('stub'))
            {
                this.find('input').each(function(e){
                    if (params.get(e.name) == undefined)
                        params.set(e.name, e.value);
                });
            }
            this.ajax(params);
        }
    },

    getDefaultOptions: function()
    {
        return {
            submitOnEnter: true,
            checkForChanges: false
        };
    },

    observeEvent: function()
    {
        var me = this;
        if (this.options.submitOnEnter)
        {
            this.view.observe('keypress', function(event){
                if (event.keyCode == 13 && (event.target.tagName=='INPUT'))
                    me.save();
            });
        }
        this.find('.submit').invoke('observe', 'click', function(){
            var action = this.getAttribute('action');
            if (action) me.processAction(action);
            else me.save();
        });
    },

	forceRefresh: function()
	{
		this.isForceRefresh = true;
		this.refresh();
	},

    refresh: function()
    {
        if (this.options.checkForChanges && this.checkForChanges())
        {
            if (!confirm('Do you want to discard all changes?')) return;
            else this.discardAllChanges();
        }
        this.submit();
    },

    save: function()
    {
        this.ajaxMethod = 'post';
        if (!this.options.checkForChanges || this.checkForChanges())
        {
            this.setAction('Save');
            this.checkForFilterChanges();
            this.submit();
        }
        else if (this.checkForFilterChanges())
        {
            this.submit();
        }
        this.ajaxMethod = 'get';
    },

    submit: function()
    {
        this.fire('beforeSubmit');
        this.beforeSubmit();
        if (this.hashable && !this.getAction() && classDefined(HashLocation))
        {
			if (this.isForceRefresh)
			{
                this.onHashChange(getLocationHash());
			}
			else
			{
				var params = this.getHashable();
				this.setHash(this.name, params);
			}
        }
        else
        {
            this.ajax(this.serialize());
        }
    },

    getHashable: function()
    {
        var elements = this.find('input:not(.nohash)', 'select:not(.nohash)', 'textarea:not(.nohash)');
        return unescape(Form.serializeElements(elements));
    },

    setValue: function(e, value)
    {
        if (Object.isUndefined(e.originValue)) e.originValue = e.value;
        if (value != e.originValue)
        {
            e.addClassName('changed');
            e.value = value;
        }
    }
});